﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using dbgservlib;

namespace wfdbg
{
    public partial class Form_Stack : ToolWindow
    {
        private IDbgService m_pDbgService;
        private bool m_bRefresh = false;
        private Timer m_timer = null;
        Object StackLock = new Object();

        public Form_Stack(IDbgService pDbgService)
        {
            m_pDbgService = pDbgService;
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form_Stack));
            InitializeComponent();

            m_timer = new Timer();
            m_timer.Tick += new EventHandler(RefreshImp);
            m_timer.Interval = 500;
            m_timer.Enabled = true;
        }

        protected override string GetPersistString()
        {
            return GetType().ToString();
        }

        public void RefreshStack()
        {
            m_bRefresh = true;
        }

        private void RefreshImp(object sender, EventArgs e)
        {
            if (IsDisposed)
                return;

            lock (StackLock)
            {
                if (m_bRefresh == false)
                    return;

                m_bRefresh = false;

                uint Frames = 0;
                try
                {
                    m_pDbgService.GetStackFrameCount(out Frames);
                }
                catch (Exception /*exc*/)
                {
                }

                if (Frames == 0)
                    return;

                bool bIsX64 = false;
                try
                {
                    m_pDbgService.IsPointer64Bit();
                    bIsX64 = true;
                }
                catch(Exception /*exc*/)
                {
                    bIsX64 = false;
                }

                listView_Stack.Items.Clear();
                for (uint count = 0; count < Frames; count++)
                {
                    tagDBG_STACK_FRAME StackFrame;
                    try
                    {
                        m_pDbgService.GetStackFrame(count, out StackFrame);
                        ListViewItem item = new ListViewItem();
                        item.Text = count.ToString();
                        if (bIsX64)
                        {
                            item.SubItems.Add(
                                StackFrame.Params[0].ToString("X16")
                                + " " + StackFrame.Params[1].ToString("X16")
                                + " " + StackFrame.Params[2].ToString("X16")
                                + " " + StackFrame.Params[3].ToString("X16")
                                );
                            item.SubItems.Add(((uint)StackFrame.InstructionOffset).ToString("X16"));
                        }
                        else
                        {
                            item.SubItems.Add(
                                ((uint)StackFrame.Params[0]).ToString("X8")
                                + " " + ((uint)StackFrame.Params[1]).ToString("X8")
                                + " " + ((uint)StackFrame.Params[2]).ToString("X8")
                                + " " + ((uint)StackFrame.Params[3]).ToString("X8")
                                );
                            item.SubItems.Add(((uint)StackFrame.InstructionOffset).ToString("X8"));
                        }

                        string NearSymbol;
                        ulong Displacement;

                        m_pDbgService.GetNearNameByOffset(StackFrame.InstructionOffset, 0, out NearSymbol, out Displacement);

                        if (NearSymbol != null)
                        {
                            if (Displacement != 0)
                                item.SubItems.Add(NearSymbol + "+" + Displacement.ToString("X"));
                            else
                                item.SubItems.Add(NearSymbol);
                        }

                        ListViewItem value = listView_Stack.Items.Add(item);
                    }
                    catch (Exception /*exc*/)
                    {
                        break;
                    }
                }
                listView_Stack.Refresh();
            }
        }
    }
}
